/**
 *
 * The MIT License
 *
 * Copyright (c) 2008 Board of Trustees, Leland Stanford Jr. University. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.macdadi.multi.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import org.macdadi.core.client.auth.AuthService;
import org.macdadi.core.client.auth.AuthenticatedUser;
import org.macdadi.core.client.auth.AuthenticationControl;
import org.macdadi.core.client.auth.AuthorizationException;
import org.macdadi.core.client.domain.DataService;
import org.macdadi.core.client.domain.ExtendedProjectInfo;
import org.macdadi.multi.client.components.*;

/**
 * @author Ben Suter <ben.suter@gmail.com>
 */
public class Overview implements EntryPoint, AuthenticationControl.AuthenticationListener, HistoryListener, FilteredProjectListing
{
    private static final Images images = (Images) GWT.create(Images.class);
    protected DockPanel panel;
    protected AuthenticationControl authControl;
    protected ProjectListing projectListing;
    protected ProjectListingControls projectListingControls;
    protected WidgetDialog searchProjectsDialog;
    protected static AuthenticatedUser currentUser;

    public interface Images extends ImageBundle
    {
        AbstractImagePrototype logoRight();
    }

    public void onModuleLoad()
    {
        /* Allow users to log in and out, and respond
         * to these changes by adjusting the UI accordingly.
         */
        authControl = new AuthenticationControl();
        authControl.setListener(this);

        buildUI();

        /* Listen for history changes. Each history token
         * corresponds to a particular filter setting applied
         * to the ProjectListing.
         */
        History.addHistoryListener(this);

        /* Unless otherwise specified, start with listing of all projects */
        String initToken = History.getToken();
        if (initToken.length() == 0) {
            History.newItem("all");
        } else {
            onHistoryChanged(initToken);
        }
    }

    public void buildUI()
    {
        panel = new DockPanel();
        panel.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        panel.setSpacing(20);
        panel.setHeight("100%");
        panel.setStyleName("macdadi-Overview");

        /* The top panel displays a title and the login/logout links */
        VerticalPanel top = new VerticalPanel();
        top.setWidth("100%");
        Widget title = new HTML("<h2>Multi-Attribute, Collaborative Design, Analysis, and Decision Integration</h2>");
        top.add(title);
        Widget description = new HTML("<style type='text/css'>  p {font-family: arial; font-size: medium} </style>" +
        		"<p> Design teams need to define goals, propose options, analyze these options with respect to the goals, and make decisions. " +
        		"Design is a social process; they need to coordinate these processes and information amongst a wide range of team members and stakeholders. " +
        		"Design is a technical process. They need to assemble and integrate all of this information efficiently and effectively. " +
        		"MACDADI: Multi-Attribute Collective Decision Assistance for a Design Initiative, is designed to help teams collect, synthesize and hierarchically organize the project goals; establish their relative preference with respect to these goals; analyze design options with respect to the goals; and visualize and assess these goals, options, preferences, and analyses to assist in a transparent and formal decision making process.</p>");
        top.add(authControl);
        top.add(description);
        top.setCellHorizontalAlignment(title, HasAlignment.ALIGN_LEFT);
        top.setCellHorizontalAlignment(authControl, HasAlignment.ALIGN_RIGHT);

        VerticalPanel center = new VerticalPanel();
        center.setWidth("100%");
        center.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        projectListingControls = new ProjectListingControls();
        if ( getCurrentUser() == null ) {
            projectListingControls.setEnabledCreateNew(false);
            projectListingControls.setEnabledYours(false);
        }
        center.add(projectListingControls);
        projectListing = new ProjectListing();
        center.add(projectListing);
        top.add(center);
        
        VerticalPanel bottom = new VerticalPanel();
        bottom.setWidth("100%");

        Widget information = new HTML("<style type='text/css'>  p {font-family: arial; font-size: x-small} </style>" +
        								"<p> This site provides access to prototype software that is intended to ease the technical and social challenges of performing multi attribute, collective design integration. Please feel free to start your own decisions, participate in others, and help us improve the software and theory. " +
										"For questions or comments about MACDADI theory and methods, please contact haymaker@stanford.edu. " +
										"For questions or comments about the software, please contact jwei512@stanford.edu </p>");
        bottom.add(information);
        bottom.setCellVerticalAlignment(information, HasAlignment.ALIGN_BOTTOM);
        
        /* The right side panel has a fixed width and arranges auxiliary
         * elements vertically, right-aligned: logo, sign-up, news
         */
        VerticalPanel rightSide = new VerticalPanel();
        rightSide.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        rightSide.setStyleName("macdadi-RightSide");
        Widget logo = images.logoRight().createImage();
        rightSide.add(logo);
        rightSide.setCellHorizontalAlignment(logo, HasAlignment.ALIGN_RIGHT);
        rightSide.add(new CreateAccountPanel());
        rightSide.add(new NewsPanel());
        
        panel.add(rightSide, DockPanel.EAST);
        panel.add(top, DockPanel.NORTH);   
        panel.add(bottom, DockPanel.SOUTH);
        
        panel.setCellHorizontalAlignment(rightSide, HasAlignment.ALIGN_RIGHT);

        searchProjectsDialog = new WidgetDialog(new SearchProjectsPanel(this), "Please enter search terms");

        RootPanel.get().add(panel);
    }

    /**
     * Respond to changes in the history token, either in response to the user
     * clicking the back or forward browser buttons, or in response to
     * internal-hyperlink-induced state changes.
     *
     * @param historyToken the token representing the current history state
     */
    public void onHistoryChanged(String historyToken)
    {
        if ( "all".equals(historyToken) ) {
            listProjects(null, false, false);
        } else if ( "recent".equals(historyToken) ) {
            listProjects(null, true, false);
        } else if ( "yours".equals(historyToken) ) {
            listProjects(null, false, true);
        } else if ( "search".equals(historyToken) ) {
            searchProjectsDialog.show(projectListingControls.getAbsoluteLeft() + 20, projectListingControls.getAbsoluteTop() + 20);
        } else {
            /* An unknown history token was encountered, instead we show all projects.
             * Note that this handles login and logout clicks as well.
             */
            History.newItem("all");
        }
    }

    public void listProjects(String[] keywords, boolean recentOnly, boolean membershipOnly)
    {
        //GWT.log("Overview.listProjects", null);
        
        DataService.App.getInstance().listProjects(keywords, recentOnly, membershipOnly, getCurrentAuthToken(), new AsyncCallback()
        {
            public void onFailure(Throwable caught)
            {
                GWT.log("Failed to populate the projects table", caught);
                if (caught instanceof AuthorizationException) {
                    projectListingControls.setMessage("Please login to view projects");
                }
            }

            public void onSuccess(Object result)
            {
                ExtendedProjectInfo[] projects = (ExtendedProjectInfo[]) result;
                projectListing.displayProjects(projects);
                
                String msg;
                int numProjects = projects.length;
                if ( numProjects == 0 )
                    msg = "There are no matching projects";
                else if (  numProjects == 1 )
                    msg = "Showing one matching project";
                else
                    msg = "Showing " + numProjects + " projects";

                projectListingControls.setMessage(msg);
            }
        });
    }

    public void userAuthenticated(AuthenticatedUser user)
    {
        currentUser = user;
        projectListingControls.setEnabledCreateNew(true);
        projectListingControls.setEnabledYours(true);
    }

    public void userLoggedOut()
    {
        currentUser = null;
        projectListingControls.setEnabledCreateNew(false);
        projectListingControls.setEnabledYours(false);
    }

    public static AuthenticatedUser getCurrentUser() {
        return currentUser;
    }

    public static String getCurrentAuthToken() {
        if ( currentUser == null )
            return null;
        else
            return currentUser.getAuthToken();
    }

    public static void checkOperationAuthorized(String target, String operation, AsyncCallback callback) {
        AuthService.App.getInstance().isAuthorizedOperation(getCurrentAuthToken(), -1, target, operation, callback);    
    }

}
